package com.zhiche.lisa.bms.service.psup.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiche.lisa.bms.dao.mapper.psup.PsupBaseDataMapper;
import com.zhiche.lisa.bms.dao.model.psup.PsupBaseData;
import com.zhiche.lisa.bms.enums.SdCommonEnum;
import com.zhiche.lisa.bms.pojo.dto.util.LspFleetDTO;
import com.zhiche.lisa.bms.pojo.vo.psup.PsupBaseDataVO;
import com.zhiche.lisa.bms.service.psup.PsupBaseDataService;
import com.zhiche.lisa.bms.service.utils.LspUtil;
import com.zhiche.lisa.bms.utils.ToolCommonUtils;
import com.zhiche.lisa.core.supports.BaseException;
import com.zhiche.lisa.core.utils.Account.AccountUtil;
import com.zhiche.lisa.core.utils.Account.JwtAccountVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 人送供方基础信息维护 服务实现类
 * </p>
 *
 * @author linbao
 * @since 2019-06-18
 */
@Service
@Slf4j
public class PsupBaseDataServiceImpl extends ServiceImpl<PsupBaseDataMapper, PsupBaseData> implements PsupBaseDataService {

    @Autowired
    private LspUtil lspUtil;

    /**
     * 分页查询
     *
     * @param page
     * @return
     */
    @Override
    public Page<PsupBaseDataVO> querySdBaseDataInfoPage(Page<PsupBaseData> page) {
        log.info("PsupBaseDataServiceImpl.querySdBaseDataInfoPage param: {}", page);
        EntityWrapper<PsupBaseData> ew = this.buildCondition(page.getCondition());
        List<PsupBaseData> psupBaseDataList = baseMapper.selectPage(page, ew);

        Page<PsupBaseDataVO> voPage = new Page<>();
        BeanUtils.copyProperties(page, voPage);
        if (CollectionUtils.isNotEmpty(psupBaseDataList)) {
            List<PsupBaseDataVO> voList = Lists.newArrayList();
            psupBaseDataList.forEach(baseData -> {
                PsupBaseDataVO vo = new PsupBaseDataVO();
                BeanUtils.copyProperties(baseData, vo);
                voList.add(vo);
            });
            voPage.setRecords(voList);
        }
        return voPage;
    }

    /**
     * 条件查询获取数据
     *
     * @param condition
     * @return
     */
    @Override
    public List<PsupBaseDataVO> querySdBaseDataInfoByCondition(Map<String, Object> condition) {
        EntityWrapper<PsupBaseData> ew = this.buildCondition(condition);
        List<PsupBaseData> psupBaseDataList = baseMapper.selectList(ew);
        if (CollectionUtils.isNotEmpty(psupBaseDataList)) {
            List<PsupBaseDataVO> voList = Lists.newArrayList();
            psupBaseDataList.forEach(baseData -> {
                PsupBaseDataVO vo = new PsupBaseDataVO();
                BeanUtils.copyProperties(baseData, vo);
                // 转换
                // 生效时间
                if (Objects.nonNull(baseData.getEffectiveDate())) {
                    vo.setEffectiveDateStr(new DateTime(baseData.getEffectiveDate()).toString(ToolCommonUtils.yyyyMMdd));
                }
                // 失效时间
                if (Objects.nonNull(baseData.getInvalidDate())) {
                    vo.setInvalidDateStr(new DateTime(baseData.getInvalidDate()).toString(ToolCommonUtils.yyyyMMdd));
                }
                // 油价联动
                if (Objects.nonNull(baseData.getLinkFlag())) {
                    vo.setLinkFlagStr(SdCommonEnum.getOilLinkFlagValue(baseData.getLinkFlag()));
                }
                // 优先级
                if (Objects.nonNull(baseData.getPriority())) {
                    vo.setPriorityStr(SdCommonEnum.getLevelValue(baseData.getPriority()));
                }
                // 状态
                if (Objects.nonNull(baseData.getStatus())) {
                    vo.setStatusStr(SdCommonEnum.getStatusValue(baseData.getStatus()));
                }
                // 价格模式
                if (Objects.nonNull(baseData.getPriceModel())) {
                    vo.setPriceModelStr(SdCommonEnum.getPriceModelValue(baseData.getPriceModel()));
                }
                voList.add(vo);
            });
            return voList;
        }
        return null;
    }

    /**
     * 人送基础信息的新增
     *
     * @param psupBaseData
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void createSdBaseDataInfo(PsupBaseData psupBaseData) {
        log.info("PsupBaseDataServiceImpl.createSdBaseDataInfo param: {}", psupBaseData);
        this.verifyParam(psupBaseData, false);
        psupBaseData.setGmtCreate(new Date());
        // 2019-10-30 创建人
        JwtAccountVO account = AccountUtil.getAccountInfoFromSecurityContext();
        psupBaseData.setCreatorName(account.getUsername());
        this.insert(psupBaseData);
    }

    /**
     * 针对excel导入数据批量信息
     *
     * @param psupBaseDataVOList
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<String> batchImportExcelData(List<PsupBaseDataVO> psupBaseDataVOList, String token) {
        log.info("PsupBaseDataServiceImpl.batchImportExcelData param: {}", psupBaseDataVOList);
        if (CollectionUtils.isNotEmpty(psupBaseDataVOList)) {
            List<String> resultStrList = Lists.newArrayList();
            List<PsupBaseData> insertBaseDataList = Lists.newArrayList();

            // 数据校验
            List<String> resultMsgList = this.verifyInsertParam(psupBaseDataVOList, token);
            if (CollectionUtils.isNotEmpty(resultMsgList)) {
                return resultMsgList;
            }
            JwtAccountVO account = AccountUtil.getAccountInfoFromSecurityContext();
            for (int i = 0, n = psupBaseDataVOList.size(); i < n; i++) {
                PsupBaseDataVO psupBaseDataVO = psupBaseDataVOList.get(i);
                StringBuilder sb = new StringBuilder();
                PsupBaseData psupBaseData = new PsupBaseData();
                BeanUtils.copyProperties(psupBaseDataVO, psupBaseData);

                // 数据转换
                if (SdCommonEnum.PRICE_MODEL_TRADITION.getValue().equals(psupBaseDataVO.getPriceModelStr())) {
                    psupBaseData.setPriceModel(SdCommonEnum.PRICE_MODEL_TRADITION.getCode());
                } else if (SdCommonEnum.PRICE_MODEL_DRIVER_SEND.getValue().equals(psupBaseDataVO.getPriceModelStr())) {
                    psupBaseData.setPriceModel(SdCommonEnum.PRICE_MODEL_DRIVER_SEND.getCode());
                } else if (SdCommonEnum.PRICE_MODEL_FIXED_PRICE.getValue().equals(psupBaseDataVO.getPriceModelStr())) {
                    psupBaseData.setPriceModel(SdCommonEnum.PRICE_MODEL_FIXED_PRICE.getCode());
                }
                // 是否联动
                if (SdCommonEnum.IS_LINK_YES.getValue().equals(psupBaseDataVO.getLinkFlagStr())) {
                    psupBaseData.setLinkFlag((SdCommonEnum.IS_LINK_YES.getCode()));
                } else if (SdCommonEnum.IS_LINK_YES.getValue().equals(psupBaseDataVO.getLinkFlagStr())) {
                    psupBaseData.setLinkFlag((SdCommonEnum.IS_LINK_YES.getCode()));
                }
                // 优先级
                if (SdCommonEnum.LEVEL_0.getValue().equals(psupBaseDataVO.getPriorityStr())) {
                    psupBaseData.setPriority((SdCommonEnum.LEVEL_0.getCode()));
                } else if (SdCommonEnum.LEVEL_1.getValue().equals(psupBaseDataVO.getPriorityStr())) {
                    psupBaseData.setPriority((SdCommonEnum.LEVEL_1.getCode()));
                } else if (SdCommonEnum.LEVEL_2.getValue().equals(psupBaseDataVO.getPriorityStr())) {
                    psupBaseData.setPriority((SdCommonEnum.LEVEL_2.getCode()));
                }
                psupBaseData.setGmtCreate(new Date());
                // 2019-10-30 创建人
                psupBaseData.setCreatorName(account.getUsername());

                insertBaseDataList.add(psupBaseData);
            }
            if (CollectionUtils.isNotEmpty(insertBaseDataList)) {
                this.insertBatch(insertBaseDataList);
            }
            return resultStrList;
        }
        return null;
    }

    /**
     * 人送基础信息的新增
     *
     * @param psupBaseData
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updateSdBaseDataInfo(PsupBaseData psupBaseData) {
        log.info("PsupBaseDataServiceImpl.updateSdBaseDataInfo param: {}", psupBaseData);
        this.verifyParam(psupBaseData, true);
        this.updateById(psupBaseData);
    }

    /**
     * 批量审核人送基础信息
     *
     * @param idList
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<String> auditSdBaseDataInfo(List<Long> idList) {
        this.verifyDeleteAndAudit(idList, "存在非新增数据, 不可审核!");
        List<PsupBaseData> psupBaseDataList = this.selectBatchIds(idList);
        List<PsupBaseData> updateBaseDataList = Lists.newArrayList();
        List<String> resultMgt = Lists.newArrayList();
        JwtAccountVO account = AccountUtil.getAccountInfoFromSecurityContext();
        psupBaseDataList.forEach(psupBaseData -> {
            // TODO 校验有效期是否冲突
            boolean verifyResult = this.verifyRuleClash(psupBaseData);
            if (!verifyResult) {
                // 时间冲突, 校验不通过
                StringBuilder msg = new StringBuilder();
                msg.append("车队-优先级:").append(psupBaseData.getFleetName())
                        .append("-").append(SdCommonEnum.getLevelValue(psupBaseData.getPriority()))
                        .append(":同一优先级有效期冲突");
                resultMgt.add(msg.toString());
            } else {
                // 2019-10-30 审核人
                psupBaseData.setActivitiName(account.getUsername());
                psupBaseData.setStatus(SdCommonEnum.AUDIT.getCode());
                updateBaseDataList.add(psupBaseData);
            }
        });
        if (CollectionUtils.isNotEmpty(updateBaseDataList)) {
            this.updateBatchById(updateBaseDataList);
        }
        return resultMgt;
    }

    /**
     * 批量删除
     *
     * @param idList
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void deleteSdBaseDataInfo(List<Long> idList) {
        this.verifyDeleteAndAudit(idList, "存在非新增数据, 不可删除!");
        this.deleteBatchIds(idList);
    }

    /**
     * 规则有效期校验
     *
     * @param psupBaseData
     * @return true-不冲突, false-时间冲突
     */
    @Override
    public boolean verifyRuleClash(PsupBaseData psupBaseData) {
        Map<String, Object> condition = Maps.newHashMap();
        condition.put("priority", psupBaseData.getPriority());
        condition.put("fleetId", psupBaseData.getFleetId());
        condition.put("status", SdCommonEnum.AUDIT.getCode());
        if (Objects.nonNull(psupBaseData.getEffectiveDate())) {
            condition.put("effectiveDate", new DateTime(psupBaseData.getEffectiveDate()).toString(ToolCommonUtils.yyyyMMdd));
        }
        if (Objects.nonNull(psupBaseData.getInvalidDate())) {
            condition.put("invalidDate", new DateTime(psupBaseData.getInvalidDate()).toString(ToolCommonUtils.yyyyMMdd));
        }
        condition.put("notEqId", psupBaseData.getId());
        Integer count = baseMapper.countRuleClashDate(condition);
        if (count <= 0) {
            return true;
        }
        return false;
    }

    /**
     * 获取对应的人送基础信息 - 根据优先级
     *
     * @param psupBaseData
     * @return
     */
    @Override
    public List<PsupBaseData> querySdBaseDataInfoByOrderLevel(PsupBaseData psupBaseData) {
        Map<String, Object> condition = Maps.newHashMap();
        condition.put("fleetId", psupBaseData.getFleetId());
        condition.put("status", SdCommonEnum.AUDIT.getCode());
        if (Objects.nonNull(psupBaseData.getEffectiveDate())) {
            condition.put("effectiveDate", new DateTime(psupBaseData.getEffectiveDate()).toString(ToolCommonUtils.yyyyMMdd));
        }
        if (Objects.nonNull(psupBaseData.getInvalidDate())) {
            condition.put("invalidDate", new DateTime(psupBaseData.getInvalidDate()).toString(ToolCommonUtils.yyyyMMdd));
        }
        return baseMapper.matchSdBaseData(condition);
    }


    /**
     * 新增和修改的参数校验
     *
     * @param psupBaseData
     * @param isUpdate
     */
    private void verifyParam(PsupBaseData psupBaseData, boolean isUpdate) {
        if (Objects.isNull(psupBaseData)) {
            throw new BaseException("参数为空");
        }
        if (isUpdate && Objects.isNull(psupBaseData.getId())) {
            throw new BaseException("参数为空, 请选择数据!");
        }
        // 车队信息
        if (Objects.isNull(psupBaseData.getFleetId()) || StringUtils.isBlank(psupBaseData.getFleetName())) {
            throw new BaseException("车队信息为空!");
        }
        // 是否油价联动
        if (Objects.isNull(psupBaseData.getLinkFlag())) {
            throw new BaseException("油价联动为空!");
        }
        // 生效时间
        if (Objects.isNull(psupBaseData.getEffectiveDate())) {
            throw new BaseException("生效时间为空!");
        }
        // 失效时间
        if (Objects.isNull(psupBaseData.getInvalidDate())) {
            throw new BaseException("失效时间为空!");
        }
        if (psupBaseData.getEffectiveDate().compareTo(psupBaseData.getInvalidDate()) > 0) {
            throw new BaseException("有效时间大于失效时间");
        }
        // 比例相加为1
        BigDecimal totalRate = BigDecimal.ZERO;
        // 油预付
        BigDecimal oilPrepayRate = psupBaseData.getOilPrepayRate() == null ? BigDecimal.ZERO : psupBaseData.getOilPrepayRate();
        totalRate = totalRate.add(oilPrepayRate);
        // 油尾款
        BigDecimal oilFinalRate = psupBaseData.getOilFinalRate() == null ? BigDecimal.ZERO : psupBaseData.getOilFinalRate();
        totalRate = totalRate.add(oilFinalRate);
        // 现金预付
        BigDecimal cashPrepayRate = psupBaseData.getCashPrepayRate() == null ? BigDecimal.ZERO : psupBaseData.getCashPrepayRate();
        totalRate = totalRate.add(cashPrepayRate);
        // 现金尾款
        BigDecimal cashFinalRate = psupBaseData.getCashFinalRate() == null ? BigDecimal.ZERO : psupBaseData.getCashFinalRate();
        totalRate = totalRate.add(cashFinalRate);
        if (totalRate.compareTo(BigDecimal.ONE) != 0) {
            throw new BaseException("比例相加不等予1!");
        }
        // 优先级
        if (Objects.isNull(psupBaseData.getPriority())) {
            throw new BaseException("优先级为空!");
        }
        // 价格模式
        if (Objects.isNull(psupBaseData.getPriceModel())) {
            throw new BaseException("价格模式为空!");
        }
        // 油价 - 根据是否油价联动来的
        if (SdCommonEnum.IS_LINK_YES.getCode().equals(psupBaseData.getLinkFlag())) {
            if (Objects.isNull(psupBaseData.getGasolinePrice()) || Objects.isNull(psupBaseData.getDieselPrice())) {
                throw new BaseException("已选择油价联动, 但是油价为空!");
            }
        }
    }

    /**
     * 封装查询条件
     *
     * @param condition
     * @return
     */
    private EntityWrapper<PsupBaseData> buildCondition(Map<String, Object> condition) {
        EntityWrapper<PsupBaseData> ew = new EntityWrapper<>();
        ew.orderBy("id desc");
        if (Objects.nonNull(condition)) {
            // 车队
            Object fleetId = condition.get("fleetId");
            if (Objects.nonNull(fleetId) && StringUtils.isNotBlank(fleetId.toString())) {
                ew.eq("fleet_id", fleetId);
            }
            Object fleetName = condition.get("fleetName");
            if (Objects.nonNull(fleetName) && StringUtils.isNotBlank(fleetName.toString())) {
                ew.eq("fleet_name", fleetName);
            }
            // 价格模式
            Object priceModel = condition.get("priceModel");
            if (Objects.nonNull(priceModel) && StringUtils.isNotBlank(priceModel.toString())) {
                ew.eq("price_model", priceModel);
            }
            // 优先级
            Object priority = condition.get("priority");
            if (Objects.nonNull(priority) && StringUtils.isNotBlank(priority.toString())) {
                ew.eq("priority", priority);
            }
            // 状态
            Object status = condition.get("status");
            if (Objects.nonNull(status) && StringUtils.isNotBlank(status.toString())) {
                ew.eq("status", status);
            }
            // 时间
            Object effectiveDateObj = condition.get("effectiveDate");
            if (Objects.nonNull(effectiveDateObj) && StringUtils.isNotBlank(effectiveDateObj.toString())) {
                Date effectiveDate = ToolCommonUtils.getDateByStr(effectiveDateObj.toString(), ToolCommonUtils.yyyyMMdd);
                ew.le("effective_date", effectiveDate);
                ew.ge("invalid_date", effectiveDate);
            }
        }
        return ew;
    }

    /**
     * 校验是否存在非新增状态的数据
     *
     * @param idList
     * @param returnErrorMsg
     */
    private void verifyDeleteAndAudit(List<Long> idList, String returnErrorMsg) {
        if (CollectionUtils.isEmpty(idList)) {
            throw new BaseException("请选择数据!");
        }
        EntityWrapper<PsupBaseData> ew = new EntityWrapper<>();
        ew.in("id", idList);
        ew.ne("status", SdCommonEnum.NEW.getCode());
        int notNewCount = this.selectCount(ew);
        if (notNewCount > 0) {
            throw new BaseException(returnErrorMsg);
        }
    }

    /**
     * 查询车队信息
     *
     * @param baseDataInfoList
     * @param token
     * @return
     */
    private Map<String, Long> getFleetMap(List<PsupBaseDataVO> baseDataInfoList, String token) {
        List<LspFleetDTO> dtoList = Lists.newArrayList();
        baseDataInfoList.stream()
                .filter(baseDataVO -> StringUtils.isNotBlank(baseDataVO.getFleetName()))
                .forEach(baseDataVO -> {
                    LspFleetDTO lspFleetDTO = new LspFleetDTO();
                    lspFleetDTO.setFleetName(baseDataVO.getFleetName());
                    dtoList.add(lspFleetDTO);
                });
        List<LspFleetDTO> fleetList = lspUtil.getFleetAll(dtoList, token);
        if (CollectionUtils.isNotEmpty(fleetList)) {
            Map<String, Long> fleetMap = Maps.newHashMap();
            fleetList.forEach(fleet -> {
                fleetMap.put(fleet.getFleetName(), fleet.getId());
            });
            return fleetMap;
        }
        return null;
    }

    /**
     * 校验数据并获取车队id
     *
     * @param baseDataInfoList
     * @param token
     * @return
     */
    private List<String> verifyInsertParam(List<PsupBaseDataVO> baseDataInfoList, String token) {
        Map<String, Long> fleetMap = getFleetMap(baseDataInfoList, token);
        if (Objects.nonNull(fleetMap)) {
            baseDataInfoList.stream()
                    .filter(fixedPriceVO -> StringUtils.isNotBlank(fixedPriceVO.getFleetName()))
                    .forEach(fixedPriceVO -> {
                        Long fleetId = fleetMap.get(fixedPriceVO.getFleetName());
                        if (Objects.nonNull(fleetId)) {
                            fixedPriceVO.setFleetId(fleetId);
                        }
                    });
        }
        List<String> resultMsgList = Lists.newArrayList();
        for (int i = 0, n = baseDataInfoList.size(); i < n; i++) {
            PsupBaseDataVO baseDataVO = baseDataInfoList.get(i);
            StringBuilder sb = new StringBuilder();
            if (Objects.isNull(baseDataVO.getEffectiveDate())) {
                sb.append("生效日期为空!");
            }
            if (Objects.isNull(baseDataVO.getInvalidDate())) {
                sb.append("失效日期为空!");
            }
            if (StringUtils.isBlank(sb) && StringUtils.isBlank(baseDataVO.getPriceModelStr())) {
                sb.append("价格模式为空!");
            }
            if (StringUtils.isBlank(sb) && StringUtils.isBlank(baseDataVO.getPriorityStr())) {
                sb.append("优先级为空!");
            }
            if (StringUtils.isBlank(sb) && StringUtils.isBlank(baseDataVO.getLinkFlagStr())) {
                sb.append("是否联动为空!");
            }
            if (StringUtils.isBlank(sb) && StringUtils.isBlank(baseDataVO.getFleetName())) {
                sb.append("车队名称为空!");
            }
            if (StringUtils.isNotBlank(sb)) {
                sb.insert(0, "行数:第" + (i + 1) + "行:");
                resultMsgList.add(sb.toString());
            }
        }
        return resultMsgList;
    }
}
